package com.txby.platformCore.component.service;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSON;
import com.jck.mybatis.log.GlobalLogAnnotation;
import com.jck.mybatis.log.TxbyLogger;
import com.jck.mybatis.mapper.MybatisBaseDaoCRUD;
import com.jck.mybatis.util.IdWorker;
import com.jck.tools.ChkUtil;
import com.jck.tools.GetIp;
import com.jck.tools.Times;

import io.undertow.servlet.spec.HttpServletRequestImpl;

@Aspect  
@Configuration
public class GlobalLogAspectInterceptor { 
	private static Logger log = Logger.getLogger(GlobalLogAspectInterceptor.class);
	@Resource(name="mybatisBaseDaoCRUD")
	private MybatisBaseDaoCRUD   mBaseDao;
	/**
	 * 请求过程，前，中，后
	 */
	private String[] requestProgress={"请求前","请求中","请求后"};
	/**
	 * ok正常,exc异常
	 */
	private String[] logStatus={"ok","exc"};
	/**
	 * 请求地址
	 */
	private  static String getRequestURL="";
	/**
	 * 请求方式
	 */
	private  static String getMethod="";
	/**
	 * 请求类方法
	 */
	private  static String getSignatureString="";
	/**
	 * 请求类方法参数
	 */
	private  static String getArgs="";
	/**
	 * 创建时间yyyy-MM-dd HH:mm:ss
	 */
	private  static String createTimeStr ="";
	/**
	 * 创建时间毫秒
	 */
	private  static long createTimeMill ;
	/**
	 * 自定义日志级别
	 */
	private  static String  level="TXBY_LOG" ;
	/**
	 * ip地址
	 */
	private  static String  ip="";
      
	@Value("${spring.datasource.logSql}")   
    private  String logSql;  
      
    @Pointcut("@annotation(com.jck.mybatis.log.GlobalLogAnnotation)")
    public void controllerMethodPointcut(){}
      
    @Around("controllerMethodPointcut()") //指定拦截器规则；也可以直接把“execution(* com.xjj………)”写进这里  
    public Object Interceptor(ProceedingJoinPoint pjp){  
        MethodSignature signature = (MethodSignature) pjp.getSignature();  
        Method method = signature.getMethod(); //获取被拦截的方法  
        GlobalLogAnnotation gla=method.getAnnotation(GlobalLogAnnotation.class);
        String methodName = method.getName(); //获取被拦截的方法名  
        Set<Object> allParams = new LinkedHashSet<>(); //保存所有请求参数，用于输出到日志中  
       	ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = requestAttributes.getRequest();
		 Date curDate=new Date();
		 Map jsonMsg=new HashMap();
		 String requestType="http";
		if(request instanceof HttpServletRequestImpl){
			requestType="http";
			getRequestURL=request.getRequestURL().toString();
			getMethod=request.getMethod();
			getSignatureString=pjp.getSignature().toString();
			getArgs=Arrays.toString(pjp.getArgs());
			createTimeStr=Times.getDateToString(curDate);
			createTimeMill= curDate.getTime();
			Signature st=pjp.getSignature();
			try {
				ip=GetIp.getIpAddr(request);
			} catch (Exception e1) {
				e1.printStackTrace();
				log.error("logStatus-"+logStatus[1]+requestProgress[0]+"描述："+gla.discription()+"；请求地址："+getRequestURL+"；请求方式:"+getMethod+"；请求类方法:"+getSignatureString+"；请求类方法参数:"+getArgs+"；message:request请求获取ip地址错误");
			}
			Map logMsg=new HashMap();
			logMsg.put("getRequestURL", getRequestURL);
			logMsg.put("getMethod", getMethod);
			logMsg.put("getSignatureString", getSignatureString);
			logMsg.put("getArgs", getArgs);
			logMsg.put("createTimeStr", createTimeStr);
			logMsg.put("createTimeMill",createTimeMill);
			logMsg.put("level",level);
			logMsg.put("ip",ip);
			logMsg.put("discription",gla.discription());
			logMsg.put("requestProgress",requestProgress[0]);
			logMsg.put("logStatus",logStatus[0]);
			
			logMsg.put("id", IdWorker.get50UUID());
			logMsg.put("requestType", requestType);
			jsonMsg=logMsg;
		 
			
		}else{
			requestType="method";
			Map logMsg=new HashMap();
			logMsg.put("getRequestURL", getRequestURL);
			logMsg.put("getMethod", getMethod);
			logMsg.put("getSignatureString", getSignatureString);
			logMsg.put("getArgs", getArgs);
			logMsg.put("createTimeStr", createTimeStr);
			logMsg.put("createTimeMill",createTimeMill);
			logMsg.put("level",level);
			logMsg.put("ip",ip);
			logMsg.put("discription",gla.discription());
			logMsg.put("requestProgress",requestProgress[0]);
			logMsg.put("logStatus",logStatus[0]);
			
			logMsg.put("id", IdWorker.get50UUID());
			logMsg.put("requestType", requestType);
			jsonMsg=logMsg;
	 
		}
		
        Object result = null;  
        boolean  flag = true;  
  
        Object[] args = pjp.getArgs();  
        for(Object arg : args){  
            if (arg instanceof Map<?, ?>) {  
                //提取方法中的MAP参数，用于记录进日志中  
                @SuppressWarnings("unchecked")  
                Map<String, Object> map = (Map<String, Object>) arg;  
                allParams.add(map);  
            }else if(arg instanceof HttpServletRequest){  
                request = (HttpServletRequest) arg;
                //获取query string 或 posted form data参数  
                Map<String, String[]> paramMap = request.getParameterMap();  
                if(paramMap!=null && paramMap.size()>0){  
                    allParams.add(paramMap);  
                }  
            }else if(arg instanceof HttpServletResponse){  

//            		System.out.println("HttpServletResponse");
            }else{  
            	
            	System.out.println("other");
            }  
        }  
          
        try {  
            if(result == null){  
                // 一切正常的情况下，继续执行被拦截的方法  
                result = pjp.proceed();  
            }  
        } catch (Throwable e) {  
        	Map logMsg=new HashMap();
			logMsg.put("getRequestURL", getRequestURL);
			logMsg.put("getMethod", getMethod);
			logMsg.put("getSignatureString", getSignatureString);
			logMsg.put("getArgs", getArgs);
			logMsg.put("createTimeStr", createTimeStr);
			logMsg.put("createTimeMill",createTimeMill);
			logMsg.put("level",level);
			logMsg.put("ip",ip);
			logMsg.put("discription",gla.discription());
			
			logMsg.put("id", IdWorker.get50UUID());
			logMsg.put("requestType", requestType);
			logMsg.put("requestProgress",requestProgress[1]);
			logMsg.put("logStatus",logStatus[1]);
			logMsg.put("message", e.getStackTrace());
			jsonMsg=logMsg;
			flag=false;
            executeLog(gla, jsonMsg);
        }  
        
        if(flag){
        	
        	Map logMsg=new HashMap();
        	logMsg.put("getRequestURL", getRequestURL);
        	logMsg.put("getMethod", getMethod);
        	logMsg.put("getSignatureString", getSignatureString);
        	logMsg.put("getArgs", getArgs);
        	logMsg.put("createTimeStr", createTimeStr);
        	logMsg.put("createTimeMill",createTimeMill);
        	logMsg.put("level",level);
        	logMsg.put("ip",ip);
        	logMsg.put("discription",gla.discription());
        	
        	
        	logMsg.put("id", IdWorker.get50UUID());
        	logMsg.put("requestType", requestType);
        	logMsg.put("requestProgress",requestProgress[2]);
        	logMsg.put("logStatus",logStatus[0]);
        	jsonMsg=logMsg;
        	executeLog(gla, jsonMsg);
        }
          
        return result;  
    }  
    
    private void executeLog(GlobalLogAnnotation gla,Map logMsg) {
   	 logSql=logSql.replace("$id", "'"+logMsg.get("id")+"'").replace("$jsonMsg",  "'"+JSON.toJSONString(logMsg)+"'").replace("$createTime", "'"+Times.getDateToString(new Date())+"'").replace("$logCategory", "1");
		  if (gla.logType() == 2) {
				TxbyLogger.getLogger(TxbyLogger.class).log(TxbyLogger.getTxbyLoggerLevel(), JSON.toJSONString(logMsg));
				mBaseDao.executeSql(logSql, null);
			} else if (gla.logType() == 3) {
				TxbyLogger.getLogger(TxbyLogger.class).log(TxbyLogger.getTxbyLoggerLevel(), JSON.toJSONString(logMsg));
				
				// mongodb save
			} else {
				TxbyLogger.getLogger(TxbyLogger.class).log(TxbyLogger.getTxbyLoggerLevel(), JSON.toJSONString(logMsg));
			}
    }
    /**
     * 保存日志到db
     * @param mBaseDao
     * @param logMsg
     */
    public   int   saveLog(Map logMsg) {
    	if(ChkUtil.isEmpty(logMsg.get("id"))) logMsg.put("id", IdWorker.get50UUID());
    	 logSql=logSql.replace("$id", "'"+logMsg.get("id")+"'").replace("$jsonMsg",  "'"+JSON.toJSONString(logMsg)+"'").replace("$createTime", "'"+Times.getDateToString(new Date())+"'").replace("$logCategory", "2");
    		TxbyLogger.getLogger(TxbyLogger.class).log(TxbyLogger.getTxbyLoggerLevel(), JSON.toJSONString(logMsg));
    		return mBaseDao.executeSql(logSql, null);
    }
      
 
}  